package com.datagateway.component;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 负载均衡管理器
 * 负责多实例部署和负载分发，提高系统的可扩展性和高可用性
 * 
 * @author Data Gateway Team
 * @version 1.0.0
 */
@Component
public class LoadBalancerManager {

    private static final Logger logger = LoggerFactory.getLogger(LoadBalancerManager.class);

    @Autowired
    private AlertManager alertManager;

    @Autowired
    private SystemMonitor systemMonitor;

    /**
     * 负载均衡统计信息
     */
    private final AtomicLong totalRequests = new AtomicLong(0);
    private final AtomicLong totalSuccessfulRequests = new AtomicLong(0);
    private final AtomicLong totalFailedRequests = new AtomicLong(0);
    private final AtomicLong totalResponseTime = new AtomicLong(0);

    /**
     * 负载均衡配置
     */
    private boolean loadBalancingEnabled = true;
    private String defaultStrategy = "ROUND_ROBIN";
    private int healthCheckIntervalSeconds = 30;
    private int maxRetryAttempts = 3;
    private int connectionTimeoutMs = 5000;
    private int readTimeoutMs = 10000;

    /**
     * 实例管理
     */
    private final Map<String, ServiceInstance> instances = new ConcurrentHashMap<>();
    private final Map<String, LoadBalancingStrategy> strategies = new ConcurrentHashMap<>();
    private final AtomicReference<LoadBalancingStrategy> currentStrategy = new AtomicReference<>();

    /**
     * 健康检查
     */
    private final ScheduledExecutorService healthCheckExecutor = Executors.newScheduledThreadPool(2, r -> {
        Thread t = new Thread(r, "load-balancer-health-check");
        t.setDaemon(true);
        return t;
    });

    /**
     * 请求分发
     */
    private final ExecutorService requestExecutor = Executors.newFixedThreadPool(10, r -> {
        Thread t = new Thread(r, "load-balancer-request");
        t.setDaemon(true);
        return t;
    });

    /**
     * 初始化负载均衡管理器
     */
    public void initialize() {
        try {
            // 初始化负载均衡策略
            initializeLoadBalancingStrategies();
            
            // 设置默认策略
            setLoadBalancingStrategy(defaultStrategy);
            
            // 启动健康检查
            startHealthCheck();
            
            logger.info("负载均衡管理器初始化成功");
            
        } catch (Exception e) {
            logger.error("负载均衡管理器初始化失败", e);
            alertManager.sendSystemErrorAlert("负载均衡管理器初始化失败", e.getMessage());
        }
    }

    /**
     * 停止负载均衡管理器
     */
    public void stop() {
        try {
            healthCheckExecutor.shutdown();
            requestExecutor.shutdown();
            
            if (!healthCheckExecutor.awaitTermination(30, TimeUnit.SECONDS)) {
                healthCheckExecutor.shutdownNow();
            }
            
            if (!requestExecutor.awaitTermination(30, TimeUnit.SECONDS)) {
                requestExecutor.shutdownNow();
            }
            
            logger.info("负载均衡管理器停止成功");
            
        } catch (Exception e) {
            logger.error("负载均衡管理器停止失败", e);
        }
    }

    /**
     * 添加服务实例
     * 
     * @param instanceId 实例ID
     * @param host 主机地址
     * @param port 端口
     * @param weight 权重
     * @return 是否添加成功
     */
    public boolean addServiceInstance(String instanceId, String host, int port, int weight) {
        try {
            ServiceInstance instance = new ServiceInstance(
                instanceId,
                host,
                port,
                weight,
                InstanceStatus.HEALTHY,
                System.currentTimeMillis()
            );
            
            instances.put(instanceId, instance);
            
            logger.info("服务实例已添加: {} -> {}:{} (权重: {})", instanceId, host, port, weight);
            
            return true;
            
        } catch (Exception e) {
            logger.error("添加服务实例失败: {}", instanceId, e);
            alertManager.sendSystemErrorAlert("添加服务实例失败", e.getMessage());
            return false;
        }
    }

    /**
     * 移除服务实例
     * 
     * @param instanceId 实例ID
     * @return 是否移除成功
     */
    public boolean removeServiceInstance(String instanceId) {
        try {
            ServiceInstance removed = instances.remove(instanceId);
            if (removed != null) {
                logger.info("服务实例已移除: {}", instanceId);
                return true;
            }
            
            return false;
            
        } catch (Exception e) {
            logger.error("移除服务实例失败: {}", instanceId, e);
            return false;
        }
    }

    /**
     * 选择服务实例
     * 
     * @return 选中的服务实例
     */
    public ServiceInstance selectInstance() {
        if (!loadBalancingEnabled || instances.isEmpty()) {
            return null;
        }

        try {
            LoadBalancingStrategy strategy = currentStrategy.get();
            if (strategy == null) {
                logger.warn("未设置负载均衡策略，使用默认策略");
                strategy = strategies.get("ROUND_ROBIN");
            }
            
            List<ServiceInstance> healthyInstances = getHealthyInstances();
            if (healthyInstances.isEmpty()) {
                logger.warn("没有健康的服务实例可用");
                return null;
            }
            
            ServiceInstance selected = strategy.selectInstance(healthyInstances);
            if (selected != null) {
                selected.incrementRequestCount();
                totalRequests.incrementAndGet();
            }
            
            return selected;
            
        } catch (Exception e) {
            logger.error("选择服务实例失败", e);
            return null;
        }
    }

    /**
     * 分发请求
     * 
     * @param request 请求数据
     * @return 请求结果
     */
    public CompletableFuture<RequestResult> distributeRequest(Object request) {
        CompletableFuture<RequestResult> future = new CompletableFuture<>();
        
        requestExecutor.submit(() -> {
            try {
                ServiceInstance instance = selectInstance();
                if (instance == null) {
                    future.complete(new RequestResult(null, false, "没有可用的服务实例", System.currentTimeMillis()));
                    return;
                }
                
                long startTime = System.currentTimeMillis();
                boolean success = sendRequestToInstance(instance, request);
                long responseTime = System.currentTimeMillis() - startTime;
                
                totalResponseTime.addAndGet(responseTime);
                
                if (success) {
                    totalSuccessfulRequests.incrementAndGet();
                    instance.incrementSuccessCount();
                    future.complete(new RequestResult(instance, true, "请求成功", responseTime));
                } else {
                    totalFailedRequests.incrementAndGet();
                    instance.incrementFailureCount();
                    future.complete(new RequestResult(instance, false, "请求失败", responseTime));
                }
                
            } catch (Exception e) {
                totalFailedRequests.incrementAndGet();
                logger.error("分发请求失败", e);
                future.complete(new RequestResult(null, false, "请求异常: " + e.getMessage(), System.currentTimeMillis()));
            }
        });
        
        return future;
    }

    /**
     * 设置负载均衡策略
     * 
     * @param strategyName 策略名称
     * @return 是否设置成功
     */
    public boolean setLoadBalancingStrategy(String strategyName) {
        try {
            LoadBalancingStrategy strategy = strategies.get(strategyName);
            if (strategy != null) {
                currentStrategy.set(strategy);
                this.defaultStrategy = strategyName;
                logger.info("负载均衡策略已设置: {}", strategyName);
                return true;
            }
            
            logger.warn("未找到负载均衡策略: {}", strategyName);
            return false;
            
        } catch (Exception e) {
            logger.error("设置负载均衡策略失败: {}", strategyName, e);
            return false;
        }
    }

    /**
     * 获取服务实例状态
     * 
     * @param instanceId 实例ID
     * @return 实例状态
     */
    public ServiceInstance getInstanceStatus(String instanceId) {
        return instances.get(instanceId);
    }

    /**
     * 获取所有服务实例状态
     * 
     * @return 实例状态列表
     */
    public List<ServiceInstance> getAllInstanceStatus() {
        return new ArrayList<>(instances.values());
    }

    /**
     * 获取健康的服务实例
     * 
     * @return 健康实例列表
     */
    public List<ServiceInstance> getHealthyInstances() {
        return instances.values().stream()
            .filter(instance -> instance.getStatus() == InstanceStatus.HEALTHY)
            .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
    }

    /**
     * 获取负载均衡统计信息
     * 
     * @return 统计信息
     */
    public LoadBalancingStatistics getStatistics() {
        return new LoadBalancingStatistics(
            totalRequests.get(),
            totalSuccessfulRequests.get(),
            totalFailedRequests.get(),
            totalResponseTime.get(),
            instances.size(),
            getHealthyInstances().size(),
            loadBalancingEnabled,
            defaultStrategy,
            healthCheckIntervalSeconds,
            maxRetryAttempts,
            System.currentTimeMillis()
        );
    }

    /**
     * 设置负载均衡配置
     * 
     * @param enabled 是否启用负载均衡
     * @param strategy 默认策略
     * @param healthCheckInterval 健康检查间隔
     * @param maxRetries 最大重试次数
     * @param connectionTimeout 连接超时时间
     * @param readTimeout 读取超时时间
     */
    public void setLoadBalancingConfig(boolean enabled, String strategy, int healthCheckInterval,
                                     int maxRetries, int connectionTimeout, int readTimeout) {
        this.loadBalancingEnabled = enabled;
        this.defaultStrategy = strategy;
        this.healthCheckIntervalSeconds = healthCheckInterval;
        this.maxRetryAttempts = maxRetries;
        this.connectionTimeoutMs = connectionTimeout;
        this.readTimeoutMs = readTimeout;
        
        // 更新策略
        setLoadBalancingStrategy(strategy);
        
        logger.info("负载均衡配置已更新: 启用={}, 策略={}, 健康检查间隔={}, 最大重试={}, 连接超时={}, 读取超时={}", 
                   enabled, strategy, healthCheckInterval, maxRetries, connectionTimeout, readTimeout);
    }

    /**
     * 初始化负载均衡策略
     */
    private void initializeLoadBalancingStrategies() {
        // 轮询策略
        strategies.put("ROUND_ROBIN", new RoundRobinStrategy());
        
        // 随机策略
        strategies.put("RANDOM", new RandomStrategy());
        
        // 加权轮询策略
        strategies.put("WEIGHTED_ROUND_ROBIN", new WeightedRoundRobinStrategy());
        
        // 最少连接策略
        strategies.put("LEAST_CONNECTIONS", new LeastConnectionsStrategy());
        
        // 响应时间策略
        strategies.put("RESPONSE_TIME", new ResponseTimeStrategy());
        
        logger.info("负载均衡策略初始化完成: {} 个策略", strategies.size());
    }

    /**
     * 启动健康检查
     */
    private void startHealthCheck() {
        healthCheckExecutor.scheduleAtFixedRate(this::performHealthCheck, 
            0, healthCheckIntervalSeconds, TimeUnit.SECONDS);
    }

    /**
     * 执行健康检查
     */
    private void performHealthCheck() {
        try {
            for (ServiceInstance instance : instances.values()) {
                boolean isHealthy = checkInstanceHealth(instance);
                
                if (isHealthy && instance.getStatus() != InstanceStatus.HEALTHY) {
                    instance.setStatus(InstanceStatus.HEALTHY);
                    logger.info("服务实例恢复健康: {}", instance.getInstanceId());
                } else if (!isHealthy && instance.getStatus() == InstanceStatus.HEALTHY) {
                    instance.setStatus(InstanceStatus.UNHEALTHY);
                    logger.warn("服务实例变为不健康: {}", instance.getInstanceId());
                    alertManager.sendSystemErrorAlert("服务实例不健康", 
                        "实例 " + instance.getInstanceId() + " 健康检查失败");
                }
            }
            
        } catch (Exception e) {
            logger.error("健康检查执行失败", e);
        }
    }

    /**
     * 检查实例健康状态
     * 
     * @param instance 服务实例
     * @return 是否健康
     */
    private boolean checkInstanceHealth(ServiceInstance instance) {
        try {
            // 这里可以实现具体的健康检查逻辑
            // 例如：发送HTTP请求到健康检查端点
            // 简化实现：随机返回健康状态
            return Math.random() > 0.1; // 90%的概率返回健康
            
        } catch (Exception e) {
            logger.error("检查实例健康状态失败: {}", instance.getInstanceId(), e);
            return false;
        }
    }

    /**
     * 向实例发送请求
     * 
     * @param instance 服务实例
     * @param request 请求数据
     * @return 是否成功
     */
    private boolean sendRequestToInstance(ServiceInstance instance, Object request) {
        try {
            // 这里可以实现具体的请求发送逻辑
            // 例如：HTTP请求、RPC调用等
            // 简化实现：模拟请求处理
            Thread.sleep(10 + (int)(Math.random() * 50)); // 模拟10-60ms的响应时间
            
            // 模拟90%的成功率
            return Math.random() > 0.1;
            
        } catch (Exception e) {
            logger.error("向实例发送请求失败: {}", instance.getInstanceId(), e);
            return false;
        }
    }

    /**
     * 服务实例类
     */
    public static class ServiceInstance {
        private final String instanceId;
        private final String host;
        private final int port;
        private final int weight;
        private InstanceStatus status;
        private final long createTime;
        private long lastHealthCheckTime;
        private long requestCount;
        private long successCount;
        private long failureCount;
        private long totalResponseTime;

        public ServiceInstance(String instanceId, String host, int port, int weight, 
                             InstanceStatus status, long createTime) {
            this.instanceId = instanceId;
            this.host = host;
            this.port = port;
            this.weight = weight;
            this.status = status;
            this.createTime = createTime;
            this.lastHealthCheckTime = createTime;
        }

        // Getter和Setter方法
        public String getInstanceId() { return instanceId; }
        public String getHost() { return host; }
        public int getPort() { return port; }
        public int getWeight() { return weight; }
        public InstanceStatus getStatus() { return status; }
        public void setStatus(InstanceStatus status) { this.status = status; }
        public long getCreateTime() { return createTime; }
        public long getLastHealthCheckTime() { return lastHealthCheckTime; }
        public void setLastHealthCheckTime(long lastHealthCheckTime) { this.lastHealthCheckTime = lastHealthCheckTime; }
        public long getRequestCount() { return requestCount; }
        public void incrementRequestCount() { this.requestCount++; }
        public long getSuccessCount() { return successCount; }
        public void incrementSuccessCount() { this.successCount++; }
        public long getFailureCount() { return failureCount; }
        public void incrementFailureCount() { this.failureCount++; }
        public long getTotalResponseTime() { return totalResponseTime; }
        public void addResponseTime(long responseTime) { this.totalResponseTime += responseTime; }
        
        public double getSuccessRate() {
            return requestCount > 0 ? (double) successCount / requestCount : 0.0;
        }
        
        public double getAverageResponseTime() {
            return requestCount > 0 ? (double) totalResponseTime / requestCount : 0.0;
        }
    }

    /**
     * 实例状态枚举
     */
    public enum InstanceStatus {
        HEALTHY,    // 健康
        UNHEALTHY,  // 不健康
        MAINTENANCE // 维护中
    }

    /**
     * 请求结果类
     */
    public static class RequestResult {
        private final ServiceInstance instance;
        private final boolean success;
        private final String message;
        private final long responseTime;

        public RequestResult(ServiceInstance instance, boolean success, String message, long responseTime) {
            this.instance = instance;
            this.success = success;
            this.message = message;
            this.responseTime = responseTime;
        }

        // Getter方法
        public ServiceInstance getInstance() { return instance; }
        public boolean isSuccess() { return success; }
        public String getMessage() { return message; }
        public long getResponseTime() { return responseTime; }
    }

    /**
     * 负载均衡策略接口
     */
    public interface LoadBalancingStrategy {
        ServiceInstance selectInstance(List<ServiceInstance> instances);
    }

    /**
     * 轮询策略
     */
    public static class RoundRobinStrategy implements LoadBalancingStrategy {
        private final AtomicLong counter = new AtomicLong(0);

        @Override
        public ServiceInstance selectInstance(List<ServiceInstance> instances) {
            if (instances.isEmpty()) {
                return null;
            }
            int index = (int) (counter.getAndIncrement() % instances.size());
            return instances.get(index);
        }
    }

    /**
     * 随机策略
     */
    public static class RandomStrategy implements LoadBalancingStrategy {
        @Override
        public ServiceInstance selectInstance(List<ServiceInstance> instances) {
            if (instances.isEmpty()) {
                return null;
            }
            int index = (int) (Math.random() * instances.size());
            return instances.get(index);
        }
    }

    /**
     * 加权轮询策略
     */
    public static class WeightedRoundRobinStrategy implements LoadBalancingStrategy {
        private final AtomicLong counter = new AtomicLong(0);

        @Override
        public ServiceInstance selectInstance(List<ServiceInstance> instances) {
            if (instances.isEmpty()) {
                return null;
            }
            
            int totalWeight = instances.stream().mapToInt(ServiceInstance::getWeight).sum();
            if (totalWeight == 0) {
                return instances.get(0);
            }
            
            long current = counter.getAndIncrement() % totalWeight;
            int weightSum = 0;
            
            for (ServiceInstance instance : instances) {
                weightSum += instance.getWeight();
                if (current < weightSum) {
                    return instance;
                }
            }
            
            return instances.get(0);
        }
    }

    /**
     * 最少连接策略
     */
    public static class LeastConnectionsStrategy implements LoadBalancingStrategy {
        @Override
        public ServiceInstance selectInstance(List<ServiceInstance> instances) {
            if (instances.isEmpty()) {
                return null;
            }
            
            return instances.stream()
                .min(Comparator.comparingLong(ServiceInstance::getRequestCount))
                .orElse(instances.get(0));
        }
    }

    /**
     * 响应时间策略
     */
    public static class ResponseTimeStrategy implements LoadBalancingStrategy {
        @Override
        public ServiceInstance selectInstance(List<ServiceInstance> instances) {
            if (instances.isEmpty()) {
                return null;
            }
            
            return instances.stream()
                .min(Comparator.comparingDouble(ServiceInstance::getAverageResponseTime))
                .orElse(instances.get(0));
        }
    }

    /**
     * 负载均衡统计信息类
     */
    public static class LoadBalancingStatistics {
        private final long totalRequests;
        private final long totalSuccessfulRequests;
        private final long totalFailedRequests;
        private final long totalResponseTime;
        private final int totalInstances;
        private final int healthyInstances;
        private final boolean loadBalancingEnabled;
        private final String defaultStrategy;
        private final int healthCheckInterval;
        private final int maxRetryAttempts;
        private final long timestamp;

        public LoadBalancingStatistics(long totalRequests, long totalSuccessfulRequests, long totalFailedRequests,
                                     long totalResponseTime, int totalInstances, int healthyInstances,
                                     boolean loadBalancingEnabled, String defaultStrategy, int healthCheckInterval,
                                     int maxRetryAttempts, long timestamp) {
            this.totalRequests = totalRequests;
            this.totalSuccessfulRequests = totalSuccessfulRequests;
            this.totalFailedRequests = totalFailedRequests;
            this.totalResponseTime = totalResponseTime;
            this.totalInstances = totalInstances;
            this.healthyInstances = healthyInstances;
            this.loadBalancingEnabled = loadBalancingEnabled;
            this.defaultStrategy = defaultStrategy;
            this.healthCheckInterval = healthCheckInterval;
            this.maxRetryAttempts = maxRetryAttempts;
            this.timestamp = timestamp;
        }

        // Getter方法
        public long getTotalRequests() { return totalRequests; }
        public long getTotalSuccessfulRequests() { return totalSuccessfulRequests; }
        public long getTotalFailedRequests() { return totalFailedRequests; }
        public long getTotalResponseTime() { return totalResponseTime; }
        public int getTotalInstances() { return totalInstances; }
        public int getHealthyInstances() { return healthyInstances; }
        public boolean isLoadBalancingEnabled() { return loadBalancingEnabled; }
        public String getDefaultStrategy() { return defaultStrategy; }
        public int getHealthCheckInterval() { return healthCheckInterval; }
        public int getMaxRetryAttempts() { return maxRetryAttempts; }
        public long getTimestamp() { return timestamp; }
        
        public double getSuccessRate() {
            return totalRequests > 0 ? (double) totalSuccessfulRequests / totalRequests : 0.0;
        }
        
        public double getAverageResponseTime() {
            return totalRequests > 0 ? (double) totalResponseTime / totalRequests : 0.0;
        }
    }
}

